package com.bac.rentmap.autocomplete;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.LocalAddress;
import com.bac.rentmap.ad.flat.crawler.localaddress.LocalAddressParser;
import com.bac.rentmap.jdo.JdoSupport;
import com.bac.rentmap.model.Building;

public class DatastoreAddressAutocompleter extends JdoSupport implements
        AddressAutocomleter {
    private static final Logger log = Logger
            .getLogger(DatastoreAddressAutocompleter.class.getName());
    private LocalAddressParser localAddressParser;

    @SuppressWarnings("unchecked")
	public List<String> autocomplete(String city, String userInput) {
        if (city == null || city.isEmpty()) {
            throw new IllegalArgumentException("City is required");
        }
        if (userInput == null || userInput.isEmpty()) {
            throw new IllegalArgumentException("User input must not be empty");
        }
        LocalAddress localAddress = null;
        try {
            localAddress = localAddressParser.parse(userInput);
        } catch (IllegalArgumentException e) {
            log.info("Can't autocomplete " + userInput + " because " + e);
            return Collections.EMPTY_LIST;
        }
        log.info("Parsed " + localAddress + " from " + userInput);
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            Query query = persistenceManager.newQuery(Building.class);
            String filter = "city == cityParam && lowercaseStreet >= streetParam && lowercaseStreet <= streetBoundParam";
            String queryParameters = "String cityParam, String streetParam, String streetBoundParam";
            if (localAddress.getBuilding() != null) {
                filter = "houseNumberPrefixes == buildingParam && " + filter;
                queryParameters = "String buildingParam, " + queryParameters;
            }
            log.fine("Filter: " + filter);
            query.setFilter(filter);
            query.setRange(0, 15);
            log.fine("Query parameters: " + queryParameters);
            query.declareParameters(queryParameters);
            List<Building> buildings;
            String street = localAddress.getStreet().toLowerCase();
            if (localAddress.getBuilding() != null) {
                buildings = (List<Building>) query.executeWithArray(localAddress
                        .getBuilding().toString(), city, street,
                        street + 'я');
            } else {
                buildings = (List<Building>) query.execute(city, street,
                        street + 'я');
            }
            log.info("Found " + buildings.size() + " address suggestions");
            List<String> res = new ArrayList<String>();
            for (Building building : buildings) {
                res.add(building.getLocalAddress().toString());
            }
            return res;
        } finally {
            persistenceManager.close();
        }
    }

    @Required
    public void setLocalAddressParser(LocalAddressParser localAddressParser) {
        this.localAddressParser = localAddressParser;
    }
}
